﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.AnalysisServices.AdomdClient;
using System.Data.SqlClient;

namespace BILAB.RealTime.RowMonitor
{
    class Core
    {
        private string _adomdString = @"Provider=MSOLAP.4;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Adventure Works DW 2008 SE;Data Source=localhost";
        private string _sqlString = @"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=AdventureWorksDW2008;Data Source=localhost";
        private string _sqlSelect = "select count(*) from FactRealTimeInternetSales";
        private string _mdxSelect = "select [Measures].[Internet Sales Facts Count] on columns from [RealTimeCube]";
        private string _sqlFactInsert = "insert into dbo.FactRealTimeInternetSales select * from dbo.FactRealTimeSampleData";

        private bool inserting = true;

        private long _lastCheck = 0;

        private int _maxThread = 32;
        private AdomdConnection _adomdcx;
        private SqlConnection _sqlcx;
        private SqlConnection _insertCx;

        private SqlCommand _insertCmd;
        private SqlCommand _selectCmd;
        private AdomdCommand _adomdCmd;
        private SqlCommand _insertFactCmd;

        private List<Thread> _threadPool = new List<Thread>();


        #region inner methods
        public long LastCheck
        {
            get { return _lastCheck; }
            set { _lastCheck = value; }
        }

        private void computeOlapDelta(long value)
        {
            long DeltaSinceLastTime = LastCheck - value;
            LastCheck = value;
            if (DeltaSinceLastTime <= 0)
            {
                Console.ForegroundColor = ConsoleColor.Green;
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Red;
            }
            Console.WriteLine("Delta =  " + DeltaSinceLastTime);
        }

        private void computeSqlAndOlapDelta(long sql, long olap)
        {
            long diff = sql - olap;
            if (diff <= 0)
            {
                Console.ForegroundColor = ConsoleColor.Green;
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Red;
            }

            Console.WriteLine("Diff =  " + diff);
        }
        #endregion

        #region Thread Delegates
        private void monitor()
        {
            while (Thread.CurrentThread.IsAlive)
            {
                Console.WriteLine("Monitoring");

                string mdxResult = _adomdCmd.ExecuteCellSet().Cells[0].Value.ToString();
                long sqlrecord  = Convert.ToInt64( _selectCmd.ExecuteScalar().ToString() );

                long olaprecord = Convert.ToInt64(mdxResult) - 60398;
                string timestamp = DateTime.Now.ToString();

                // Query Logic
                StringBuilder sb =   new StringBuilder();
                //sb.Append("INSERT INTO [AdventureWorksDW2008].[dbo].[RealTimeMonitor]([Timer],[type] ,[Counter])");
                //sb.Append(" VALUES  ( convert(datetime,'");
                //sb.Append(timestamp);
                //sb.Append("',103),'SQL',");
                //sb.Append(sqlrecord);
                //sb.Append(")");
                //sb.AppendLine();
                //sb.Append("INSERT INTO [AdventureWorksDW2008].[dbo].[RealTimeMonitor]([Timer],[type] ,[Counter])");
                //sb.Append(" VALUES  ( convert(datetime,'");
                //sb.Append(timestamp);
                //sb.Append("',103),'CUBE',");
                //sb.Append(olaprecord);
                //sb.Append(")");
                sb.Append("INSERT INTO [AdventureWorksDW2008].[dbo].[RealTimeMonitor] ([Timestamp],[SQL] ,[OLAP]) VALUES");
                sb.Append("(");
                sb.Append("convert(datetime,'");
                sb.Append(timestamp);
                sb.Append("',103)");
                sb.Append(",");
                sb.Append(sqlrecord);
                sb.Append(",");
                sb.Append(olaprecord);
                sb.Append(")");
                // Insert Information into tracking Db
                _insertCmd.CommandText = sb.ToString();
                _insertCmd.ExecuteNonQuery();


                // Console Display Logic
                Console.ForegroundColor = ConsoleColor.Yellow;
                StringBuilder display = new StringBuilder();
                display.Append(timestamp);
                display.Append(" SQL = ");
                display.Append(sqlrecord);
                display.Append(" CUBE = ");
                display.Append(olaprecord);
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine(display.ToString());
               
                // Comparaison indicators
                this.computeSqlAndOlapDelta(sqlrecord, olaprecord);
                this.computeOlapDelta(olaprecord);
                Console.ForegroundColor = ConsoleColor.White;

                // wait for next execution
                Thread.Sleep(10000);
            }
        }
        private void insert()
        {
            while (Thread.CurrentThread.IsAlive)
            {
                lock (this)
                {
                    if (this.inserting)
                    {
                        int nb = _insertFactCmd.ExecuteNonQuery();
                        Console.ForegroundColor = ConsoleColor.White;
                        Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " inserting " + nb + " rows");
                        Console.ForegroundColor = ConsoleColor.White;
                    }
                    
                }
                
                Thread.Sleep(500);
            }


        }
        private void listenForInput()
        {
            while (Thread.CurrentThread.IsAlive)
            {
                Console.WriteLine("Waiting for input :");
                ConsoleKeyInfo key = Console.ReadKey();
                Console.WriteLine("here");
                if (key.KeyChar == 's')
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("stopping = " + key.KeyChar);
                    Console.ForegroundColor = ConsoleColor.White;
                    this.inserting = false;
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("starting = " + key.KeyChar);
                    Console.ForegroundColor = ConsoleColor.White;
                    this.inserting = true;
                }
                Thread.Sleep(1000);
            }
        }
        private void sendFax()
        {
        }

        #endregion

        public void start()
        {
            _adomdcx = new AdomdConnection(_adomdString);
            _adomdcx.Open();

            _sqlcx = new SqlConnection(_sqlString);
            _sqlcx.Open();

            _insertCx = new SqlConnection(_sqlString);
            _insertCx.Open();

            _insertCmd = new SqlCommand();
            _insertCmd.Connection = _sqlcx;
           

            _selectCmd = new SqlCommand(_sqlSelect, _sqlcx);
            _adomdCmd = new AdomdCommand(_mdxSelect, _adomdcx);
            _insertFactCmd = new SqlCommand(_sqlFactInsert, _insertCx);

            Console.WriteLine("Press <Enter> to end the process");
            Thread doSelect = new Thread(new ThreadStart(monitor));
            Thread keyListen = new Thread(new ThreadStart(listenForInput));

            for (int i = 0; i < _maxThread; i++)
            {
                _threadPool.Add(new Thread(new ThreadStart(insert)));                
            }
            
            foreach (Thread t in _threadPool)
            {
                t.Start();
            }

            keyListen.Start();
            doSelect.Start();            
        }

    }
}